<template>
	<view class="container">
		<view class="header">
			<text class="title">App微信支付</text>
			<text class="subtitle">使用前端签名工具类</text>
		</view>
		
		<!-- 支付配置 -->
		<view class="config-section">
			<text class="section-title">支付配置</text>
			<view class="config-item">
				<text class="label">AppID:</text>
				<input v-model="wxConfig.appid" placeholder="微信开放平台AppID" class="input" />
			</view>
			<view class="config-item">
				<text class="label">商户号:</text>
				<input v-model="wxConfig.mch_id" placeholder="微信支付商户号" class="input" />
			</view>
			<view class="config-item">
				<text class="label">API密钥:</text>
				<input v-model="wxConfig.key" placeholder="微信支付API密钥" class="input" type="password" />
			</view>
		</view>
		
		<!-- 订单信息 -->
		<view class="order-section">
			<text class="section-title">订单信息</text>
			<view class="order-item">
				<text class="label">商品描述:</text>
				<input v-model="orderInfo.body" placeholder="请输入商品描述" class="input" />
			</view>
			<view class="order-item">
				<text class="label">支付金额:</text>
				<input v-model="orderInfo.total_fee" placeholder="请输入金额(分)" class="input" type="number" />
			</view>
			<view class="order-item">
				<text class="label">订单号:</text>
				<input v-model="orderInfo.out_trade_no" placeholder="自动生成" class="input" disabled />
			</view>
		</view>
		
		<!-- 操作按钮 -->
		<view class="action-section">
			<button @click="generateOrderNo" class="btn btn-secondary">生成订单号</button>
			<button @click="generateUnifiedOrderSign" class="btn btn-primary">生成统一下单签名</button>
			<button @click="simulateAppPay" class="btn btn-success" :disabled="!prepayId">模拟App支付</button>
		</view>
		
		<!-- 签名信息显示 -->
		<view class="result-section" v-if="signResult">
			<text class="section-title">签名信息</text>
			<view class="result-item">
				<text class="result-label">签名类型:</text>
				<text class="result-value">{{signResult.type}}</text>
			</view>
			<view class="result-item">
				<text class="result-label">参数排序:</text>
				<text class="result-value">{{signResult.sortedParams}}</text>
			</view>
			<view class="result-item">
				<text class="result-label">签名字符串:</text>
				<text class="result-value">{{signResult.signString}}</text>
			</view>
			<view class="result-item">
				<text class="result-label">计算结果:</text>
				<text class="result-value sign-value">{{signResult.sign}}</text>
			</view>
		</view>
		
		<!-- 支付参数显示 -->
		<view class="params-section" v-if="payParams">
			<text class="section-title">支付参数</text>
			<view class="params-content">
				<text class="params-text">{{JSON.stringify(payParams, null, 2)}}</text>
			</view>
		</view>
		
		<!-- 测试工具 -->
		<view class="test-section">
			<text class="section-title">测试工具</text>
			<button @click="generateTestData" class="btn btn-info">生成测试数据</button>
			<button @click="verifySign" class="btn btn-warning" :disabled="!signResult">验证签名</button>
			<button @click="diagnoseSignIssues" class="btn btn-primary">诊断签名问题</button>
			<button @click="runDiagnostic" class="btn btn-secondary">运行诊断</button>
			<button @click="testUnifiedOrder" class="btn btn-success" :disabled="isLoading">测试统一下单</button>
			<button @click="testNetwork" class="btn btn-secondary">网络测试</button>
		</view>
		
		<!-- 诊断结果 -->
		<view class="diagnostic-section" v-if="diagnosticResult">
			<text class="section-title">诊断结果</text>
			<view class="diagnostic-content">
				<text class="diagnostic-text">{{diagnosticResult}}</text>
			</view>
		</view>
		
		<!-- 状态提示 -->
		<view class="status-section" v-if="statusMessage">
			<text class="status-message" :class="statusType">{{statusMessage}}</text>
		</view>
	</view>
</template>

<script>
import WxPaySignUtil from '../../utils/wxpay-sign.js'
import WxPayDebugUtil from '../../utils/wxpay-debug.js'

export default {
	data() {
		return {
			// 微信支付配置
			wxConfig: {
				appid: 'wxe281b4ec4c2ae13c', // 你的微信公众号AppID
				mch_id: '1700381946', // 你的商户号
				key: '79c16a13e46c56bc73d937cc5ac552ec', // API密钥（生产环境不能放前端）
				notify_url: 'https://api.aibaxing.com/server/api/wxPay/payNotify'
			},
			
			// 订单信息
			orderInfo: {
				body: 'App支付测试商品',
				total_fee: 1, // 0.01元 = 1分，微信支付金额必须是整数
				out_trade_no: '',
				spbill_create_ip: '127.0.0.1',
				trade_type: 'APP'
			},
			
			// 签名结果
			signResult: null,
			
			// 支付参数
			payParams: null,
			
			// 模拟的prepay_id
			prepayId: '',
			
			// 状态信息
			statusMessage: '',
			statusType: 'info',
			
			// 诊断结果
			diagnosticResult: '',
			
			// 加载状态
			isLoading: false
		}
	},
	
	onLoad() {
		this.generateOrderNo()
	},
	
	methods: {
		// 生成订单号
		generateOrderNo() {
			this.orderInfo.out_trade_no = WxPaySignUtil.generateOrderNo('APP')
			this.showStatus('订单号生成成功', 'success')
		},
		
		// 生成统一下单签名
		generateUnifiedOrderSign() {
			try {
				const result = WxPaySignUtil.prepareUnifiedOrderSign(this.wxConfig, this.orderInfo)
				
				this.signResult = {
					type: '统一下单签名',
					sortedParams: result.signInfo.sortedParams,
					signString: result.signInfo.signString,
					sign: result.signInfo.sign
				}
				
				// 模拟获取prepay_id
				this.prepayId = 'wx' + Date.now() + Math.random().toString(36).substr(2, 9)
				
				this.showStatus('统一下单签名生成成功', 'success')
				
				console.log('统一下单参数:', result.params)
				console.log('签名调试信息:', WxPaySignUtil.formatSignDebugInfo(result.signInfo))
			} catch (error) {
				this.showStatus('签名生成失败: ' + error.message, 'error')
			}
		},
		
		// 模拟App支付
		simulateAppPay() {
			try {
				const result = WxPaySignUtil.prepareAppPaySign(this.wxConfig, this.prepayId)
				
				this.payParams = result.params
				
				this.signResult = {
					type: 'App支付签名',
					sortedParams: result.signInfo.sortedParams,
					signString: result.signInfo.signString,
					sign: result.signInfo.sign
				}
				
				this.showStatus('App支付参数生成成功', 'success')
				
				console.log('App支付参数:', result.params)
				console.log('签名调试信息:', WxPaySignUtil.formatSignDebugInfo(result.signInfo))
				
				// 在真实环境中，这里会调用uni.requestPayment
				this.callWxPay(result.params)
			} catch (error) {
				this.showStatus('App支付参数生成失败: ' + error.message, 'error')
			}
		},
		
		// 调用微信支付
		async callWxPay(payParams) {
			try {
				// #ifdef APP-PLUS
				const result = await uni.requestPayment({
					provider: 'wxpay',
					orderInfo: payParams
				})
				this.showStatus('支付成功', 'success')
				console.log('支付结果:', result)
				// #endif
				
				// #ifndef APP-PLUS
				this.showStatus('当前环境不支持微信支付，请在App中测试', 'warning')
				console.log('模拟支付参数:', payParams)
				// #endif
			} catch (error) {
				this.showStatus('支付失败: ' + error.errMsg, 'error')
				console.error('支付错误:', error)
			}
		},
		
		// 验证签名
		verifySign() {
			if (!this.signResult) {
				this.showStatus('请先生成签名', 'warning')
				return
			}
			
			try {
				let params = {}
				
				if (this.signResult.type === '统一下单签名') {
					params = {
						...this.orderInfo,
						appid: this.wxConfig.appid,
						mch_id: this.wxConfig.mch_id,
						nonce_str: 'test_nonce_str',
						notify_url: this.wxConfig.notify_url,
						sign: this.signResult.sign
					}
				} else if (this.signResult.type === 'App支付签名') {
					params = {
						...this.payParams,
						sign: this.signResult.sign
					}
				}
				
				const isValid = WxPaySignUtil.verifySign(params, this.wxConfig.key)
				
				if (isValid) {
					this.showStatus('签名验证通过', 'success')
				} else {
					this.showStatus('签名验证失败', 'error')
				}
			} catch (error) {
				this.showStatus('签名验证出错: ' + error.message, 'error')
			}
		},
		
		// 诊断签名问题
		diagnoseSignIssues() {
			try {
				// 检查基本配置
				if (!this.wxConfig.appid || !this.wxConfig.mch_id || !this.wxConfig.key) {
					this.showStatus('请先完善微信支付配置', 'warning')
					return
				}
				
				if (!this.orderInfo.out_trade_no) {
					this.generateOrderNo()
				}
				
				const currentSign = this.signResult ? this.signResult.sign : null
				const diagnosis = WxPayDebugUtil.diagnoseSignVerification(this.wxConfig, this.orderInfo, currentSign)
				
				// 显示诊断结果
				this.diagnosticResult = this.formatSignDiagnosis(diagnosis)
				
				if (diagnosis.status === 'success') {
					this.showStatus('签名诊断通过，配置正常', 'success')
				} else {
					this.showStatus(`发现${diagnosis.issues.length}个问题`, 'error')
				}
				
			} catch (error) {
				this.showStatus('诊断失败: ' + error.message, 'error')
				console.error('诊断错误:', error)
			}
		},
		
		// 格式化签名诊断结果
		formatSignDiagnosis(diagnosis) {
			let result = '【签名问题诊断报告】\n'
			result += `诊断时间: ${new Date().toLocaleString()}\n\n`
			
			// 配置验证
			result += '=== 配置验证 ===\n'
			result += `AppID有效: ${diagnosis.configValidation.appidValid ? '✓' : '✗'}\n`
			result += `商户号有效: ${diagnosis.configValidation.mchIdValid ? '✓' : '✗'}\n`
			result += `API密钥有效: ${diagnosis.configValidation.keyValid ? '✓' : '✗'}\n`
			result += `订单信息有效: ${diagnosis.configValidation.orderValid ? '✓' : '✗'}\n\n`
			
			// 签名分析
			if (diagnosis.signatureAnalysis) {
				result += '=== 签名分析 ===\n'
				result += `参数数量: ${diagnosis.signatureAnalysis.parametersCount}\n`
				result += `签名长度: ${diagnosis.signatureAnalysis.actualSignLength}/32\n`
				if (diagnosis.testSignString) {
					result += `测试签名字符串:\n${diagnosis.testSignString}\n\n`
				}
			}
			
			// 问题列表
			if (diagnosis.issues.length > 0) {
				result += '=== 发现的问题 ===\n'
				diagnosis.issues.forEach((issue, index) => {
					result += `${index + 1}. ${issue}\n`
				})
				result += '\n'
			}
			
			// 解决建议
			if (diagnosis.suggestions.length > 0) {
				result += '=== 解决建议 ===\n'
				diagnosis.suggestions.forEach((suggestion, index) => {
					result += `${index + 1}. ${suggestion}\n`
				})
			}
			
			return result
		},
		
		// 生成测试数据
		generateTestData() {
			const testData = WxPaySignUtil.generateTestData(1)[0]
			
			this.orderInfo.body = '测试商品_' + testData.orderNo.slice(-6)
			this.orderInfo.total_fee = testData.amount
			this.orderInfo.out_trade_no = testData.orderNo
			
			this.showStatus('测试数据生成成功', 'success')
		},
		
		// 显示状态信息
		showStatus(message, type = 'info') {
			this.statusMessage = message
			this.statusType = type
			
			setTimeout(() => {
				this.statusMessage = ''
			}, 3000)
		},
		
		// 运行诊断
		runDiagnostic() {
			const diagnostic = WxPayDebugUtil.generateDiagnosticReport(this.wxConfig, this.orderInfo)
			this.diagnosticResult = WxPayDebugUtil.formatDebugInfo({
				timestamp: new Date().toISOString(),
				request: {
					config: this.wxConfig,
					orderInfo: this.orderInfo
				},
				diagnostic
			})
			
			if (diagnostic.config.errors.length > 0 || diagnostic.order.errors.length > 0) {
				this.showStatus('发现配置问题，请查看诊断结果', 'error')
			} else {
				this.showStatus('诊断完成，配置正常', 'success')
			}
		},
		
		// 测试统一下单
		async testUnifiedOrder() {
			this.isLoading = true
			this.showStatus('正在测试统一下单...', 'info')
			
			try {
				const result = await WxPayDebugUtil.simulateUnifiedOrder(this.wxConfig, this.orderInfo)
				const debugInfo = WxPayDebugUtil.generateDebugInfo(this.wxConfig, this.orderInfo, result)
				this.diagnosticResult = WxPayDebugUtil.formatDebugInfo(debugInfo)
				
				if (result.success) {
					this.prepayId = result.data.prepay_id
					this.showStatus('统一下单测试成功', 'success')
				} else {
					this.showStatus(`统一下单失败: ${result.error}`, 'error')
				}
			} catch (error) {
				this.showStatus('测试失败: ' + error.message, 'error')
			} finally {
				this.isLoading = false
			}
		},
		
		// 网络测试
		async testNetwork() {
			this.showStatus('正在测试网络连接...', 'info')
			
			try {
				const results = await WxPayDebugUtil.testNetworkConnection()
				let resultText = '=== 网络连接测试 ===\n'
				
				results.forEach(result => {
					if (result.success) {
						resultText += `✅ ${result.url} - ${result.responseTime}ms (状态码: ${result.status})\n`
					} else {
						resultText += `❌ ${result.url} - ${result.error}\n`
					}
				})
				
				this.diagnosticResult = resultText
				this.showStatus('网络测试完成', 'success')
			} catch (error) {
				this.showStatus('网络测试失败: ' + error.message, 'error')
			}
		}
	}
}
</script>

<style>
	.container {
		padding: 20rpx;
		min-height: 100vh;
		background-color: #f5f5f5;
	}
	
	.header {
		text-align: center;
		margin-bottom: 40rpx;
	}
	
	.title {
		font-size: 36rpx;
		font-weight: bold;
		color: #333;
		display: block;
		margin-bottom: 10rpx;
	}
	
	.subtitle {
		font-size: 24rpx;
		color: #666;
	}
	
	.config-section,
	.order-section,
	.result-section,
	.params-section,
	.test-section {
		background: white;
		margin-bottom: 30rpx;
		padding: 30rpx;
		border-radius: 20rpx;
		box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
	}
	
	.section-title {
		font-size: 28rpx;
		font-weight: bold;
		color: #333;
		display: block;
		margin-bottom: 30rpx;
		padding-bottom: 10rpx;
		border-bottom: 2rpx solid #e5e5e5;
	}
	
	.config-item,
	.order-item {
		display: flex;
		align-items: center;
		margin-bottom: 25rpx;
	}
	
	.label {
		font-size: 26rpx;
		color: #666;
		width: 140rpx;
		flex-shrink: 0;
	}
	
	.input {
		flex: 1;
		height: 60rpx;
		border: 2rpx solid #e5e5e5;
		border-radius: 10rpx;
		padding: 0 15rpx;
		font-size: 26rpx;
		background: white;
	}
	
	.input:disabled {
		background-color: #f5f5f5;
		color: #999;
	}
	
	.action-section {
		display: flex;
		flex-wrap: wrap;
		gap: 20rpx;
		margin-bottom: 30rpx;
	}
	
	.btn {
		flex: 1;
		min-width: 200rpx;
		border: none;
		border-radius: 35rpx;
		font-size: 26rpx;
		font-weight: bold;
		color: white;
		display: flex;
		align-items: center;
		justify-content: center;
	}
	
	.btn-primary {
		background: linear-gradient(135deg, #007aff 0%, #0056cc 100%);
	}
	
	.btn-secondary {
		background: linear-gradient(135deg, #6c757d 0%, #545b62 100%);
	}
	
	.btn-success {
		background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%);
	}
	
	.btn-info {
		background: linear-gradient(135deg, #17a2b8 0%, #117a8b 100%);
	}
	
	.btn-warning {
		background: linear-gradient(135deg, #ffc107 0%, #d39e00 100%);
		color: #333;
	}
	
	.btn:disabled {
		background: #ccc !important;
		color: #999 !important;
	}
	
	.result-item {
		margin-bottom: 20rpx;
	}
	
	.result-label {
		font-size: 24rpx;
		color: #666;
		display: block;
		margin-bottom: 5rpx;
	}
	
	.result-value {
		font-size: 22rpx;
		color: #333;
		word-break: break-all;
		line-height: 1.4;
	}
	
	.sign-value {
		color: #007aff;
		font-weight: bold;
		font-family: monospace;
	}
	
	.params-content {
		background: #f8f9fa;
		padding: 20rpx;
		border-radius: 10rpx;
		border: 1rpx solid #e9ecef;
	}
	
	.params-text {
		font-size: 20rpx;
		color: #495057;
		font-family: monospace;
		line-height: 1.4;
		white-space: pre-wrap;
	}
	
	.status-section {
		position: fixed;
		top: 50rpx;
		left: 50%;
		transform: translateX(-50%);
		z-index: 1000;
	}
	
	.status-message {
		display: inline-block;
		padding: 20rpx 40rpx;
		border-radius: 40rpx;
		font-size: 24rpx;
		color: white;
		font-weight: bold;
		box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.2);
	}
	
	.status-message.success {
		background: #28a745;
	}
	
	.status-message.error {
		background: #dc3545;
	}
	
	.status-message.warning {
		background: #ffc107;
		color: #333;
	}
	
	.status-message.info {
		background: #17a2b8;
	}
	
	.diagnostic-section {
		background: white;
		margin-bottom: 30rpx;
		padding: 30rpx;
		border-radius: 20rpx;
		box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
	}
	
	.diagnostic-content {
		background: #f8f9fa;
		padding: 20rpx;
		border-radius: 10rpx;
		border: 1rpx solid #e9ecef;
		max-height: 600rpx;
		overflow-y: auto;
	}
	
	.diagnostic-text {
		font-size: 20rpx;
		color: #495057;
		font-family: monospace;
		line-height: 1.6;
		white-space: pre-wrap;
		word-break: break-all;
	}
</style> 